#!usr/bin/env python3
# 保存着路由的定义
from flask import request,render_template,redirect,url_for,session,flash,jsonify,abort,current_app
from flask_wtf import FlaskForm
from flask_login import login_required 
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired
from flask_login import current_user
from datetime import datetime
from . import main as mainBP
from app.auth import auth as authBP
from app.email import send_mail #注意导入的方式
from app.models import Permission,commit,User,Role,Post,Comments 
from app.decorators import premission_required,admin_required,count_fn_time
from app.main.forms import PostForm
from .forms import EditProfileForm,EditProfileAdminForm,CommentsForm,CKDemoForm
from config import getLang
from app.utils import viewUtil
from app.const import COMMENT_TIME,COMMENT_PAGE_NUM
'''
在蓝本中定义路由,使用url_for需要注意
比如在程序员路由中使用url_for("index")

在蓝本中就不一样了，Flask 会为蓝本中的全部端点加上一个命名空间，这样就可以在不
同的蓝本中使用相同的端点名定义视图函数，而不会产生冲突。命名空间就是蓝本的名字
（Blueprint 构造函数的第一个参数），所以视图函数index() 注册的端点名是main.index，
其URL 使用url_for('main.index') 获取。

url_for() 函数还支持一种简写的端点形式，在蓝本中可以省略蓝本名，例如url_for('.
index')。在这种写法中，命名空间是当前请求所在的蓝本。这意味着同一蓝本中的重定向
可以使用简写形式，但跨蓝本的重定向必须使用带有命名空间的端点名。

'''

#自定义一个表单
class NameForm(FlaskForm):
    # 每个字段都有validators参数指定验证函数列表,Required函数表示验证输入内容不能为空 
    name = StringField('请输入用户名:',id='formIpt',validators=[DataRequired('用户名不能为空')]) 
    submit = SubmitField()
	
		

@mainBP.route("/",methods=["GET","POST"])
def index():	
	form = PostForm()
	isSubmit = form.validate_on_submit()
	if isSubmit and current_user.can(Permission.WRITE_ARTICLE):
		#发表文章;原始的current_user是轻度包装的数据,_get_current_object方法获取到的是数据库实际需要的数据对象
		post = Post(title=form.title.data,body=form.text.data,author=current_user._get_current_object())
		commit([post])
		flash(getLang('postSuc'))
		return redirect(url_for("main.index")) #注意在蓝本路由中url_for的使用
	name = ''	
	if current_user.is_authenticated:
		name = current_user.username

	'''
	pageNums = current_app.config['HELLOCODE_POSTS_PER_PAGE'] #每页显示的数量
	page = request.args.get('page',1,type=int) #要第几页的从参数获取,默认选取第1页
	pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page,
		per_page=pageNums,error_out=False) #page 第几页,per_page每页显示的数量,error_out请求的页数超出了范围返回404(默认True),False表示返回空列表
	'''
	pagination = viewUtil.getPagination(Post.query.order_by(Post.timestamp.desc()))
	posts = pagination.items	
	params = {"name":name,"title":"HelloCode_V1.0.0",
			"form":form,"posts":posts,
			"current_time":datetime.utcnow(),'pagination':pagination
			}
	return render_template("index.html",**params) #渲染模板

#动态路由;注意设置动态路由的格式
@mainBP.route("/user/<string:username>")
#@login_required #限制登录用户才能访问
def user(username):
	'''
	if current_user.is_authenticated:
		return render_template("sub/user.html",name=current_user.username) 
	return redirect(url_for("auth.login"))
	'''
	user = User.query.filter_by(username=username).first()
	if user is None:		
		abort(404)
	'''
	pageNums = current_app.config['HELLOCODE_POSTS_PER_PAGE'] #每页显示的数量
	page = request.args.get('page',1,type=int) #要第几页的从参数获取,默认选取第1页
	pagination = user.posts.order_by(Post.timestamp.desc()).paginate(page,
		per_page=pageNums,error_out=False)
	posts = pagination.items
	'''
	pagination = viewUtil.getPagination(user.posts.order_by(Post.timestamp.desc()))
	posts = pagination.items	
	return render_template("sub/user.html",posts=posts,name=user.username,username=user.username,user=user,pagination=pagination) 

@mainBP.route("/about")
def about():    
    return render_template("sub/about.html")
    

@mainBP.route("/product")
def product():
    return render_template("sub/product.html",imgs=['p1.png','p2.png','p3.png'])

@mainBP.route("/product/<string:img>") #指定数据类型的路由
def product_detail(img):
    return render_template("sub/product_detail.html",img=img)

@mainBP.route("/data/<param>")
def reciveClient(param):
    logging.info(param)

@mainBP.route("/login")
def login():
	return redirect(url_for("auth.login"))

@mainBP.route("/edit-profile",methods=['GET','POST'])
@login_required
def editProfile(): #用户修改资料的页面
	editForm = EditProfileForm()	
	if editForm.validate_on_submit():
		current_user.name = editForm.name.data
		current_user.location = editForm.location.data
		current_user.about_me = editForm.about_me.data
		commit([current_user])
		flash(getLang("modifyOk"))
		return redirect(url_for('main.user',username=current_user.username))
	editForm.name.data = current_user.name
	editForm.location.data = current_user.location
	editForm.about_me.data = current_user.about_me
	return render_template("user/user_profile.html",form=editForm,user=current_user)

@mainBP.route('/post_detail/<int:id>',methods=['GET','POST'])
def post_detail(id):
	post = Post.query.get_or_404(id)
	form = CommentsForm()
	if form.validate_on_submit(): #提交评论
		if not current_user.is_authenticated:
			return redirect(url_for('auth.login'))
		newOne=current_user.comments.order_by(Comments.timestamp.desc()).first()		
		if newOne and newOne.post_id==id:
			dif = datetime.utcnow()-newOne.timestamp
			dif = round(dif.total_seconds()) 
			if dif<COMMENT_TIME:#上次发评论到现在的时间间隔 防止刷评论
				flash('你评论得太快啦')
				return redirect(url_for('.post_detail',id=id))		

		comments = Comments(author_id=current_user.id,post_id=id,body=form.body.data)
		commit([comments])		
		return redirect(url_for('.post_detail',id=id))		
	#post.comments.order_by(Comments.timestamp.desc())
	query = post.comments.filter_by(disabled=True).order_by(Comments.timestamp.desc())
	pagination = viewUtil.getPagination(query,COMMENT_PAGE_NUM)
	comments = pagination.items	
	return render_template("sub/post_detail.html",post=post,form=form,comments=comments,pagination=pagination)

#编辑博客	
@mainBP.route('/edit_post/<int:id>',methods=['GET','POST'])
@login_required
def edit_post(id):
	post = Post.query.get_or_404(id)	
	if current_user.id!=post.author.id or not current_user.is_admin():
		abort(404)
	form = PostForm()
	if form.validate_on_submit():
		post.body = form.text.data
		post.title = form.title.data
		commit([post])
		flash(getLang('eidtPostSuc'))
		return redirect(url_for('.edit_post',id=post.id))
	form.title.data = post.title
	form.text.data = post.body
	return render_template('sub/edit_post.html',form=form)

#添加上下文处理器,上下文处理器的变量是可以在所有模板中访问的,所有一些全局性的变量可以定义在这里
@mainBP.app_context_processor
def inject_permission():
	return dict(Permission=Permission,current_time=datetime.utcnow())

#测试和js通讯
import json
@mainBP.route("/convectorjs",methods=['GET','POST'])
def convectorjs():
	s = request.args.get('mykey')	
	mydata = json.loads(s)
	mydata['msgFlask'] = "Hello JS"	
	return jsonify(result=mydata)

#测试集成ckeditor
@mainBP.route('/ckeditor/test',methods=['GET','POST'])
def ckeditor():
	form = CKDemoForm()	
	if form.validate_on_submit():
		print("form.editor",form.editor.data)
	return render_template("sub/ckDM.html",form=form)